Skip to main content

Network Layer Implementation

Overview

The network layer is responsible for managing communication between the application and remote servers. Retrofit, a type-safe HTTP client for Android, simplifies network requests by providing an easy-to-use API and powerful features such as request serialization, response deserialization, and error handling. This documentation describes the structure and implementation of a network layer using Retrofit in an Android project.

Key Components

  • API Interface: Defines endpoints and request methods.
  • Retrofit Builder: Configures Retrofit instance.
  • Network Models: Represents request and response data structures.
  • Network Service: Serves as a single entry point for network operations.

Step-by-Step Implementation

  1. Add Dependencies

Include the Retrofit library and additional dependencies in your build.gradle file:

  • api ‘'com.squareup.retrofit2:retrofit:2.9.0'
  • api 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
  • api 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2'
  1. Define the API Interface

Create an interface that specifies the endpoints, HTTP methods, and request/response types.

public interface ApiInterface {
@POST(EndPoints.LOGIN)
Call<BaseResponse> doLogin(@Body LoginPayload payload);

@GET(EndPoints.Metadata)
Call<BaseResponse> getMetadata(@Query("syncver") String syncVersion);

@GET(EndPoints.Metadata)
Call<BaseResponse> getMetadata();


@POST(EndPoints.ENROLLMENT)
Call<BaseResponse> uploadChildEnrollmentForm(@Body ChildPayload payload);

}
  1. Configure Retrofit Instance

Set up a Retrofit instance with a base URL, Gson converter, and optional logging interceptor.

public class RetrofitClient {

private static final String BASE_URL = "https://..";
private static Retrofit retrofit;




public static void setupRestClient(String province) {

if (!province.equals(Core.getInstance().getAppContext().getString(R.string.default_province))) {

/*comment for live*/

HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient httpClient =getOkHttpBuilder()
.addInterceptor(chain -> {
Request request = chain.request();
Request newRequest;
newRequest = request.newBuilder()
.addHeader(KEY_HEADER, KEY)
.addHeader("AppVersion", getAppVersionName())
.build();
return chain.proceed(newRequest);
})
.addInterceptor(new HeaderInterceptor())
.connectTimeout(TIMEOUT, TimeUnit.SECONDS).
writeTimeout(TIMEOUT, TimeUnit.SECONDS).
readTimeout(TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(logging)

.build();

Gson gson = new GsonBuilder()
.setLenient()
.create();

Retrofit retrofit = new Retrofit.Builder().
baseUrl(Utils.INSTANCE.getUrl(province)).
addConverterFactory(GsonConverterFactory.create(gson)).
client(httpClient).
build();

restClient = retrofit.create(ApiInterface.class);
}
}

public static ApiInterface getAuthAdapter() {
if (restClient == null) {
Context context = Core.getInstance().getAppContext();
setupRestClient(DevicePreferences.INSTANCE.getString(context.getString(R.string.pref_province),
context.getString(R.string.default_province)));
}
return restClient;
}

}
  1. Implement Network Service

Use the RetrofitInstance to perform network operations.In this Service class we define all our network calls:

public static void doLogin(LoginPayload payload, final OnResponseReceivedListener listener) {
RestClient.getAuthAdapter().doLogin(payload).enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(@NotNull Call<BaseResponse> call, @NotNull Response<BaseResponse> response) {
if (response.body() != null) {
responseCode = response.body().getStatus();
if (responseCode == ResponseStatus.STATUS_SUCCESS.getId())
listener.onSuccessReceived(response.body());
else if (responseCode == ResponseStatus.STATUS_FAILURE.getId()) {
responseError = response.body().getParams().getError();
listener.onFailureReceived(responseError != null ? responseError : Utils.INSTANCE.getMessageByResponseCode(responseCode), responseCode);
} else if (responseCode == ResponseStatus.STATUS_INCORRECT_CREDENTIALS.getId())
listener.onFailureReceived(ResponseStatus.values()[responseCode].getMessage(), responseCode);
else
listener.onFailureReceived(Utils.INSTANCE.getMessageByResponseCode(responseCode), responseCode);
} else
listener.onFailureReceived(SERVER_SE_KOI_JAWAB_NAHI_AYA, -1);
}

@Override
public void onFailure(@NotNull Call<BaseResponse> call, @NotNull Throwable t) {
showError(t, listener);
}
});
}

public static void getMetadata(final OnResponseReceivedListener listener) {
RestClient.getAuthAdapter().getMetadata(DevicePreferences.INSTANCE.getString(DevicePreferences.SYNC_VERSION, "0")).enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(@NotNull Call<BaseResponse> call, @NotNull Response<BaseResponse> response) {
if (response.body() != null) {
responseCode = response.body().getStatus();
if (responseCode == ResponseStatus.STATUS_SUCCESS.getId()) {
if (response.body().getParams().getSyncVersion() != null)
DevicePreferences.INSTANCE.putString(DevicePreferences.SYNC_VERSION, (response.body().getParams().getSyncVersion()));
listener.onSuccessReceived(response.body());
} else
listener.onFailureReceived(Utils.INSTANCE.getMessageByResponseCode(responseCode), responseCode);
} else
listener.onFailureReceived(SERVER_SE_KOI_JAWAB_NAHI_AYA, -1);
}

@Override
public void onFailure(@NotNull Call<BaseResponse> call, @NotNull Throwable t) {
showError(t, listener);
}
});
}